﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace Zero.UControl.Component
{
    /// <summary>
    /// Pagination.xaml 的交互逻辑
    /// </summary>
    public partial class Pagination : UserControl, INotifyPropertyChanged
    {
        public Pagination()
        {
            InitializeComponent();
        }
        public event PropertyChangedEventHandler? PropertyChanged;

        #region 属性字段
        public ObservableCollection<int> PageNumbers { get; private set; } = new ObservableCollection<int>();
        public ObservableCollection<string> SubPageNumbers { get; private set; } = new ObservableCollection<string>();

        private int startPage = 1;
        public int StartPage
        {
            get { return startPage; }
            set { startPage = value; }
        }

        private int totalPages;
        public int TotalPages
        {
            get { return totalPages; }
            set
            {
                totalPages = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalPages)));
            }
        }

        #endregion

        #region 依赖属性
        public int CurrentPage
        {
            get { return (int)GetValue(CurrentPageProperty); }
            set { SetValue(CurrentPageProperty, value); }
        }

        public static readonly DependencyProperty CurrentPageProperty =
            DependencyProperty.Register("CurrentPage", typeof(int), typeof(Pagination), new PropertyMetadata(1, OnPageChanged));


        public int PageSize
        {
            get { return (int)GetValue(PageSizeProperty); }
            set { SetValue(PageSizeProperty, value); }
        }

        public static readonly DependencyProperty PageSizeProperty =
            DependencyProperty.Register("PageSize", typeof(int), typeof(Pagination), new PropertyMetadata(10, OnPropertyChanged));


        public int TotalItems
        {
            get { return (int)GetValue(TotalItemsProperty); }
            set { SetValue(TotalItemsProperty, value); }
        }

        public static readonly DependencyProperty TotalItemsProperty =
            DependencyProperty.Register("TotalItems", typeof(int), typeof(Pagination), new PropertyMetadata(10, OnPropertyChanged));


        public Action<int> DoSearch
        {
            get { return (Action<int>)GetValue(DoSearchProperty); }
            set { SetValue(DoSearchProperty, value); }
        }

        public static readonly DependencyProperty DoSearchProperty =
            DependencyProperty.Register("DoSearch", typeof(Action<int>), typeof(Pagination), new PropertyMetadata(null));

        #endregion

        #region 依赖属性方法
        private static void OnPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            int newVal = (int)e.NewValue;
            var instance = (d as Pagination);
            if (newVal < instance.StartPage)
            {
                instance.SetValue(CurrentPageProperty, instance.StartPage);
                return;
            }
            else if (newVal > instance.TotalPages)
            {
                instance.SetValue(CurrentPageProperty, instance.TotalPages);
                return;
            }

            if (CheckNew<int>(e))
            {
                instance.UpdateSubPageNumbers();
                instance.DoSearch?.Invoke(instance.CurrentPage);
            }
        }

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (CheckNew<int>(e))
            {
                var instance = (d as Pagination);
                instance.UpdatePageNumbers();
                instance.UpdateSubPageNumbers();
            }
        }

        private static bool CheckNew<T>(DependencyPropertyChangedEventArgs e)
        {
            int oldValue = (int)e.OldValue;
            int newValue = (int)e.NewValue;
            return oldValue != newValue;
        }

        #endregion

        #region 本地方法
        private void UpdatePageNumbers()
        {
            PageNumbers.Clear();
            TotalPages = TotalItems % PageSize == 0 ? TotalItems / PageSize : (TotalItems / PageSize + 1);
            
            for (int i = 0; i <= TotalPages; i++)
            {
                PageNumbers.Add(i);
            }
            CurrentPage = 1;
        }

        private void UpdateSubPageNumbers()
        {
            SubPageNumbers.Clear();
            // 去掉0号索引,开头和结尾
            if (PageNumbers.Count - 3 <= 3)
            {
                for (int i = 2; i < PageNumbers.Count - 1; i++)
                {
                    SubPageNumbers.Add(PageNumbers[i].ToString());
                }
            }
            else
            {
                /* 数据中心区域 */
                if (CurrentPage - 2 > StartPage && CurrentPage + 2 < TotalPages)
                {
                    SubPageNumbers.Add("...");
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 1].ToString());
                    SubPageNumbers.Add("...");
                }
           
                /* 起始位置和结束位置 */
                else if (CurrentPage == StartPage && CurrentPage + 2 < TotalPages)
                {
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 2].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 3].ToString());
                    SubPageNumbers.Add("...");
                }
                else if (CurrentPage - 2 > StartPage && CurrentPage == TotalPages)
                {
                    SubPageNumbers.Add("...");
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 3].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 2].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 1].ToString());
                }

                /* 间隔1个 */
                else if (CurrentPage - 1 == StartPage && CurrentPage + 1 < TotalPages)
                {
                    SubPageNumbers.Add(PageNumbers[CurrentPage].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 2].ToString());
                    SubPageNumbers.Add("...");
                }
                else if (CurrentPage - 1 > StartPage && CurrentPage + 1 == TotalPages)
                {
                    SubPageNumbers.Add("...");
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 2].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage].ToString());
                }
                /* 间隔2个 */
                else if (CurrentPage - 2 == StartPage && CurrentPage + 2 < TotalPages)
                {
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 1].ToString());
                    SubPageNumbers.Add("...");
                }
                else if (CurrentPage - 2 > StartPage && CurrentPage + 2 == TotalPages)
                {
                    SubPageNumbers.Add("...");
                    SubPageNumbers.Add(PageNumbers[CurrentPage - 1].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage].ToString());
                    SubPageNumbers.Add(PageNumbers[CurrentPage + 1].ToString());
                }
            }
        }

        private void PreviousPage_Click(object sender, RoutedEventArgs e)
        {
            if (CurrentPage > 1)
            {
                CurrentPage--;
                DoSearch?.Invoke(CurrentPage);
            }
        }

        private void NextPage_Click(object sender, RoutedEventArgs e)
        {
            if (CurrentPage < TotalPages)
            {
                CurrentPage++;
                DoSearch?.Invoke(CurrentPage);
            }
        }

        private void PageButton_Click(object sender, RoutedEventArgs e)
        {
            if (sender is RadioButton button && int.TryParse(button.Content.ToString(), out int page))
            {
                CurrentPage = page;
                DoSearch?.Invoke(CurrentPage);
            }
        }
        #endregion
    }
}
